package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import com.wiscamp.ninechapters.panels.domain.entities.Parameter;
import com.wiscamp.ninechapters.panels.domain.repositories.ParameterRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.DomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class ParameterService implements DomainService {
    private final ParameterRepository parameterRepository;

    private final String cacheName = "parameters";

    public ParameterService(ParameterRepository parameterRepository) {
        this.parameterRepository = parameterRepository;
    }

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#parameterId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Parameter getParameter(long parameterId) {
        var parameter = parameterRepository.getParameter(parameterId);
        if (Objects.isNull(parameter)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PARAMETER_NOT_FOUND, parameterId);
        }
        return parameter;
    }


    @HandleServiceException
    @CachePut(value = cacheName, key = "#parameter.parameterId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Parameter createParameter(Parameter parameter, long operatorId) {
        var existedParameter = parameterRepository.getParameterByCode(parameter.getApplicationId(), parameter.getParameterCode());
        if (Objects.nonNull(existedParameter)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PARAMETER_CODE_EXISTED, parameter);
        }

        parameter.createBy(operatorId);
        return parameterRepository.saveParameter(parameter);
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#parameter.parameterId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Parameter updateParameter(Parameter parameter, long operatorId) {
        var existedParameter = getParameter(parameter.getParameterId());
        existedParameter = parameterRepository.getParameterByCode(parameter.getApplicationId(), parameter.getParameterCode());
        if (Objects.nonNull(existedParameter) && existedParameter.getParameterId() != parameter.getParameterId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PARAMETER_CODE_EXISTED, parameter);
        }
        parameter.updateBy(operatorId);
        return parameterRepository.saveParameter(parameter);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#parameterId")
    public boolean enableParameter(long parameterId, long operatorId) {
        var parameter = getParameter(parameterId);
        if (Objects.isNull(parameter)) return false;
        // 记录操作日志
        parameter.enable();
        parameter.updateBy(operatorId);
        parameterRepository.saveParameter(parameter);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#parameterId")
    public boolean disableParameter(long parameterId, long operatorId) {
        var parameter = getParameter(parameterId);
        if (Objects.isNull(parameter)) return false;
        // 记录操作日志
        parameter.disable();
        parameter.updateBy(operatorId);
        parameterRepository.saveParameter(parameter);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#parameterId")
    public boolean deleteParameter(long parameterId, long operatorId) {
        var parameter = getParameter(parameterId);
        if (Objects.isNull(parameter)) return false;
        // 记录操作日志
        parameter.delete();
        parameter.updateBy(operatorId);
        parameterRepository.saveParameter(parameter);
        return true;
    }
}
